/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.cam.can.algorithm;

import uk.ac.cam.can.Data;
import java.util.*;

/**
 *
 * @author Thomas
 */
public class LDiverse extends KAnon{
    private int l;
    private int c;
    
    public LDiverse(Data data, int k, double d, int l, int c){
        super(data, k, d);
        this.l=l;
        this.c=c;
    }
    
    @Override
    public boolean criteria(PosGen[] combination, List<String[]> qgroup){
        if(qgroup.size()<k){
            return false;
        }else{
            for(PosGen p1 : combination){
                // we can skip this attribute if he is fully generalised
                if(qgroup.get(0)[p1.position()].equals("*"))
                    continue;
                if(data.getType(p1.position())==Data.TYPE_SENSITIVE){
                    Map<String, List<String[]>> subgroups = new HashMap<String, List<String[]>>();
                    for(String[] record : qgroup){                        
                        String quasi="";
                        for(PosGen p2 : combination){
                            if(qgroup.get(0)[p1.position()].equals("*"))
                                continue;
                            if(data.getType(p2.position())==Data.TYPE_SENSITIVE){
                                quasi+=record[p2.position()];
                            }
                        }
                        if(subgroups.containsKey(quasi)){
                            subgroups.get(quasi).add(record);
                        }else{
                            //System.out.println(qi);
                            subgroups.put(quasi, new ArrayList<String[]>());
                            subgroups.get(quasi).add(record);
                        }                        
                    }
                    // we constitued the sub groups in each of them we should l different value of p1
                    
                    for(List<String[]> subgroup : subgroups.values()){
                        // it cannot work if 
                        if(subgroup.size()<=l)
                            return false;
                        if(subGroupCriteria(subgroup, p1.position())==false)
                            return false;
                    }
                }
            }
        }
        return true;
    }
    
    private boolean subGroupCriteria(List<String[]> subgroup, int pos){
        Map<String, Integer> tmp = new HashMap<String, Integer>();
        for(String[] record : subgroup){
            if(!tmp.containsKey(record[pos])){
                tmp.put(record[pos], 1);
            }else{
                tmp.put(record[pos], tmp.get(record[pos])+1);
            }
        }
        if(tmp.size()<l)
            return false;
        
        int max = 0;
        int i = 0;
        int[] intTmp = new int[tmp.size()];
        for(int t : tmp.values()){
            intTmp[i++]=t;
            if(t > max)
                max = t;
        }
        Arrays.sort(intTmp);
        int sum = 0;
        for(int j = 0; j < intTmp.length-1; i++){
            sum+=intTmp[j];
        }
        
        if(max >= sum*c)
            return false;
        return true;
    }
}
